/*************************************************************
*
* M3D.CPP
*
* Basic init/term functionality (dummy for now)
*************************************************************/
#include <stdafx.h>

#include <float.h>

//#include <ap_comm.h>
//#include <ap_cfg.h>
#include <m3d\m3d.h>
//#include "ap/ap_dbg_var.h"

inline BOOL _isFinite(float r)
{
   // Check the 8 exponent bits.
   // Usually NAN == (exponent = all 1, mantissa = non-zero)
   //         INF == (exponent = all 1, mantissa = zero)
   // This simply checks the exponent
   CASSERT(sizeof(float) == sizeof(int));
   union {
      float f;
      unsigned int i;
   } val;

   val.f = r;
   return ((val.i & 0x7f800000) != 0x7f800000);
}

/*************************************************************
* _m3dCheckValid()
*
*************************************************************/
BOOL _m3dCheckValid (float number)
{
   //if (_isnan(number)) {     
   if (!_isFinite(number)) {     
      // MAZAFUCKERS!!! FIX -=REAL=- ISSUES INSTEAD OF COMMENTING THIS ASSERTION >:-(
      //STRONG_ASSERT(!"Infinite float value");
      return FALSE;
   }
   /*
   if (number < -M3D_INFINITY*100.f || number > M3D_INFINITY*100.f) {
   ASSERT(FALSE);
   return FALSE;
   }
   */
   return TRUE;
}

#ifndef SPU
//
// Global variables
//
int      m3dSimdType = M3D_SIMD_NONE;

//
// Static functions
//
static void  _m3dDetectSIMD (void);

/*************************************************************
* m3dInit ()
*
* Initialize M3D module
*************************************************************/
BOOL m3dInit (void )
{
   _m3dDetectSIMD();

   if (!m3dInit2DMatr()) {
      return FALSE;
   }
   if (!m3dInit3DMatr()) {
      return FALSE;
   }
   //if (!m3dInitNoise()) {
   //   return FALSE;
   //}
   return TRUE;
}

/*************************************************************
* m3dTerm ()
*
* Term M3D module
*************************************************************/
void m3dTerm (void )
{
   //m3dTermNoise();
   m3dTerm3DMatr();
   m3dTerm2DMatr();
   return;
}

//DBG_VAR_BOOL(dbg_offSimd, "debug/decomp/OFF SIMD", false);

/*************************************************************
* m3dInitHW()
*
*************************************************************/
BOOL m3dInitHW (void)
{  
   _m3dDetectSIMD();

   //#ifndef _RETAIL
   //   if (dbg_offSimd) {
   //      m3dSimdType = M3D_SIMD_NONE;
   //   }
   //#endif

   return TRUE;
}

/*************************************************************
* _m3dCheckValid()
*
*************************************************************/
BOOL _m3dCheckValid (const m4dV *v)
{
   if (!_m3dCheckValid(v->x)) {
      return FALSE;
   }
   if (!_m3dCheckValid(v->y)) {
      return FALSE;
   }
   if (!_m3dCheckValid(v->z)) {
      return FALSE;
   }
   if (!_m3dCheckValid(v->w)) {
      return FALSE;
   }

   return TRUE;
}

/*************************************************************
* _m3dCheckValid()
*
*************************************************************/
BOOL _m3dCheckValid (const m3dV *v)
{
   if (!_m3dCheckValid(v->x)) {
      return FALSE;
   }
   if (!_m3dCheckValid(v->y)) {
      return FALSE;
   }
   if (!_m3dCheckValid(v->z)) {
      return FALSE;
   }

   return TRUE;
}

/*************************************************************
* _m3dCheckValid()
*
*************************************************************/
BOOL _m3dCheckValid (const m2dV *v)
{
   if (!_m3dCheckValid(v->x)) {
      return FALSE;
   }
   if (!_m3dCheckValid(v->y)) {
      return FALSE;
   }

   return TRUE;
}

/*************************************************************
* _m3dCheckValid()
*
*************************************************************/
BOOL _m3dCheckValid (const m3dVTX *v)
{
   if (!_m3dCheckValid(v->s)) {
      return FALSE;
   }
   if (!_m3dCheckValid(v->t)) {
      return FALSE;
   }

   return TRUE;
}

/*************************************************************
* m3dDetectSIMD ()
*
*************************************************************/
static void _m3dDetectSIMD (void)
{  
   // detect CPU type
   m3dSimdType = M3D_SIMD_NONE;

//#if defined(_AP_PC)
//   __try {
//      __asm {
//         mov      eax, 1
//         cpuid
//      }
//   } __except ( 1 ) {
//      return;
//   }
//
//   __asm {
//       mov      eax, 1
//       cpuid
//       test     edx, 0x02000000
//       jz       short _noSSE
//       mov      m3dSimdType, M3D_SIMD_SSE
//       jmp      short _finish
//_noSSE:
//       test     edx, 0x80000000
//       mov      eax, 0x80000000
//       cpuid
//       cmp      eax, 0x80000001
//       jb       short _no3DNOW
//       mov      eax, 0x80000001      // Select function 0x80000001
//       cpuid
//       test     edx, 0x80000000
//       jz       _no3DNOW
//       mov      m3dSimdType, M3D_SIMD_3DNOW
//       jmp      short _finish
//_no3DNOW:
//_finish:
//   }
//
//   switch (m3dSimdType) {
//      case M3D_SIMD_SSE:      
//         apLog( "~Info~Math - SSE detected." ); 
//         //m3dSimdType = M3D_SIMD_3DNOW;
//         break;
//      case M3D_SIMD_3DNOW:    
//         apLog( "~Info~Math - 3DNOW detected." ); 
//         break;
//      default:                
//         apLog( "~Info~Math - No SIMD extensions detected." ); 
//         break;
//   }
//
//#endif   // #if defined(_AP_PC)

   return;
}

void m3dEnableSimd (BOOL enable)
{
   if (enable)
      m3dSimdType &= 0x7FFFFFFF;
   else
      m3dSimdType |= 0x80000000;
}

int m3dGetSimdType (void)
{
   return m3dSimdType & 0x7FFFFFFF;
}

#endif //SPU

//
// End of file M3D.CPP
//
